package com.cqupt.sendMes.service.Impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cqupt.sendMes.dao.RoleDao;
import com.cqupt.sendMes.dao.UserDao;
import com.cqupt.sendMes.dao.UserRoleDao;
import com.cqupt.sendMes.dto.UserDTO;
import com.cqupt.sendMes.entity.Role;
import com.cqupt.sendMes.entity.User;
import com.cqupt.sendMes.entity.UserRole;
import com.cqupt.sendMes.enums.HttpStatusEnum;
import com.cqupt.sendMes.enums.StatusEnum;
import com.cqupt.sendMes.exception.BusinessException;
import com.cqupt.sendMes.service.UserService;
import com.cqupt.sendMes.utils.*;
import com.cqupt.sendMes.vo.UserInfoVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private UserRoleDao userRoleDao;

    @Autowired
    private JwtUtil jwtUtil; // JWT 工具类，用于生成和验证 JWT

    @Autowired
    private RedisTemplate<String, String> redisTemplate;



    @Transactional  // 添加事务
    @Override
    public Boolean register(UserDTO userDTO) {
        //注册默认是普通用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,userDTO.getUsername())
                .eq(User::getStatus, StatusEnum.NO_DELETED.getCode());
        if(userDao.selectCount(queryWrapper) > 0){
            log.warn("用户名已存在，请重新输入");
            throw new BusinessException(HttpStatusEnum.USER_EXIST.getCode(),HttpStatusEnum.USER_EXIST.getMessage());
        }
        User user = new User();
        BeanUtils.copyProperties(userDTO,user); //将userDTO中的属性值复制到user中
        user.setStatus(StatusEnum.NO_DELETED.getCode());
        // 1. 保存用户信息
        userDao.insert(user);
        log.info("用户保存成功");
        // 2. 获取普通角色的ID
        Role role = roleDao.selectOne(new QueryWrapper<Role>().eq("role_name", "用户"));
        // 如果没有找到普通角色，抛出异常，触发事务回滚
        if (role == null) {
            throw new BusinessException(HttpStatusEnum.FAIL.getCode(),HttpStatusEnum.FAIL.getMessage() + " 未找到用户角色，注册失败");
        }
        log.info("普通角色信息：{}", role);

        User existUser = userDao.selectOne(queryWrapper);
        if(existUser == null){
            log.warn("新增的用户不存在，请联系管理员");
            throw new BusinessException(HttpStatusEnum.USER_NOT_FOUND.getCode(),HttpStatusEnum.USER_NOT_FOUND.getMessage());
        }

        //构造用户、关系表
        UserRole userRole = UserRole.builder()
                .userId(existUser.getId())
                .username(existUser.getUsername())
                .roleId(role.getId())
                .roleName(role.getRoleName())
                .status(StatusEnum.NO_DELETED.getCode())
                .build();
        log.info("userRole信息：{}", userRole.toString());
        // 3. 保存用户角色关系
        userRoleDao.insert(userRole);
        return true;
    }

    @Override
    public String login(UserDTO userDTO) {
        //根据用户名查询用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,userDTO.getUsername())
                .eq(User::getStatus, StatusEnum.NO_DELETED.getCode())
                .last("limit 1");

        User user = userDao.selectOne(queryWrapper);
        if (ObjectUtil.isEmpty(user)){
            log.warn("用户不存在，请重新输入");
            throw new BusinessException(HttpStatusEnum.USER_NOT_FOUND.getCode(),HttpStatusEnum.USER_NOT_FOUND.getMessage());
        }

        if (!user.getPassword().equals(userDTO.getPassword())){
            log.warn("密码错误，请重新输入");
            throw new BusinessException(HttpStatusEnum.PASSWORD_ERROR.getCode(),HttpStatusEnum.PASSWORD_ERROR.getMessage());
        }
        //查询此用户的角色信息
        LambdaQueryWrapper<UserRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserRole::getUserId,user.getId())
                .eq(UserRole::getStatus,StatusEnum.NO_DELETED.getCode());
        UserRole userRole = userRoleDao.selectOne(lambdaQueryWrapper);
        if(ObjectUtil.isNull(userRole)){
            log.warn("未找到用户角色，登录失败");
            throw new BusinessException(HttpStatusEnum.FAIL.getCode(),HttpStatusEnum.FAIL.getMessage() + " 未找到用户角色，登录失败");
        }

        ChainableMap<String, Object> claims = new ChainableMap<>();
        claims.chainPut("id", user.getId())
                .chainPut("username", user.getUsername())
                .chainPut("roleId", userRole.getRoleId())
                .chainPut("roleName", userRole.getRoleName())
                .chainPut("userUid", user.getUserUid())
                .chainPut("status", StatusEnum.NO_DELETED.getCode());
        //生成token
        String token = jwtUtil.generateToken(claims);
        //将token存入redis，生成token的摘要
        String tokenHash = SmUtil.sm3(token);
        //token有效期，24小时
        redisTemplate.opsForValue().set(tokenHash,token,60*60*24, TimeUnit.SECONDS);
        log.info("{}登录成功", userDTO.getUsername());
        return tokenHash;
    }

    @Override
    public Boolean logout() {
        Map<String, Object> claims = ThreadLocalUtil.get(); //获取当前线程中的用户信息
        if (ObjectUtil.isEmpty(claims)) {
            log.error("未查询到用户");
            return null;
        }
        String tokenHash = (String) claims.get("tokenHash");
        log.info("用户{}退出登录，删除缓存{}", claims.get("username"),tokenHash);
        return redisTemplate.delete(tokenHash);
    }

    @Override
    public UserInfoVO getUserInfo() {
        UserInfoVO userInfo = UserHelper.getCurrentUser();
        if (userInfo != null) {
            log.info("获取用户信息成功，当前用户{}", userInfo);
        }
        return userInfo;
    }

    @Override
    public PageResult<User> getUserList(UserDTO userDTO) {
        log.info("获取用户列表，pageNum:{},pageSize:{}",userDTO.getCurrentPage(),userDTO.getPageSize());
        //构造查询wrapper
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getStatus, StatusEnum.NO_DELETED.getCode())
                .like(StrUtil.isNotBlank(userDTO.getUsername()), User::getUsername,StrUtil.trim(userDTO.getUsername()))
                .like(StrUtil.isNotBlank(userDTO.getUserUid()), User::getUserUid,StrUtil.trim(userDTO.getUserUid()));
        //当前用户是否是管理员
        UserInfoVO userInfo = UserHelper.getCurrentUser();
        if (userInfo != null && userInfo.getRoleId() != 1) {
            log.info("此用户是普通用户");
            queryWrapper.eq(User::getId, userInfo.getId());
        }
        //1.设置·分页参数
        PageHelper.startPage(userDTO.getCurrentPage(),userDTO.getPageSize());
        //2、执行查询
        List<User> userList = userDao.selectList(queryWrapper);
        //3、执行封装
        PageInfo<User> pageInfo = new PageInfo<>(userList);
        log.info("查询成功，{}", pageInfo.getList());
        return PageResult.build(pageInfo.getPageNum(), pageInfo.getTotal(), pageInfo.getPageSize(), pageInfo.getList());

    }
}
